<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  <title>java反射机制 | rongshen</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/css/highlight.css">

  
  <meta name="description" content="java开发面试整理。来源：https:&#x2F;&#x2F;github.com&#x2F;Snailclimb&#x2F;JavaGuide">
<meta property="og:type" content="article">
<meta property="og:title" content="java反射机制">
<meta property="og:url" content="http://example.com/2021/01/11/java%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/index.html">
<meta property="og:site_name" content="rongshen">
<meta property="og:description" content="java开发面试整理。来源：https:&#x2F;&#x2F;github.com&#x2F;Snailclimb&#x2F;JavaGuide">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content="2021-01-11T13:53:21.000Z">
<meta property="article:modified_time" content="2021-05-07T06:44:14.677Z">
<meta property="article:author" content="John Doe">
<meta property="article:tag" content="java">
<meta name="twitter:card" content="summary"><meta name="generator" content="Hexo 6.1.0"></head>

<body>
  <div id="wrapper">
    <header id="header">
  <h1 id="title">
    <a href="/">rongshen</a>
  </h1>
  <nav>
    
    
      
      <a class="nav-link" href="/">Home</a>
    
      
        <span class="nav-spacer">×</span>
      
      <a class="nav-link" href="/archives">Archives</a>
    
      
        <span class="nav-spacer">×</span>
      
      <a class="nav-link" target="_blank" rel="noopener" href="https://github.com/Aaron-boom">Github</a>
    
      
        <span class="nav-spacer">×</span>
      
      <a class="nav-link" href="/2020/04/13/About-Me/">About</a>
    
    
  </nav>
</header>

    <div id="content">
      <article id="post-java反射机制" class="article article-type-post" itemprop="blogPost" itemscope>
  <div class="article-inner">
    
      <header class="article-header">
        
  
    <h2 class="article-title" itemprop="headline name">
      java反射机制
    </h2>
  


        <div class="article-meta">
          <time class="article-date" datetime="2021-01-11T13:53:21.000Z" itemprop="datePublished">2021-01-11</time>

          
        </div>
      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
      
        <p>java开发面试整理。来源：<a target="_blank" rel="noopener" href="https://github.com/Snailclimb/JavaGuide">https://github.com/Snailclimb/JavaGuide</a></p>
<span id="more"></span>

<blockquote>
<p>整理自：<a target="_blank" rel="noopener" href="https://github.com/Snailclimb/JavaGuide%EF%BC%8C">https://github.com/Snailclimb/JavaGuide，</a><br>Guide哥</p>
</blockquote>
<h2 id="反射机制介绍："><a href="#反射机制介绍：" class="headerlink" title="反射机制介绍："></a>反射机制介绍：</h2><p>JAVA 反射机制是在运行状态中，对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法和属性；这种动态获取的信息以及动态调用对象的方法的功能称为 java 语言的反射机制。</p>
<h2 id="获取Class对象的四种方式："><a href="#获取Class对象的四种方式：" class="headerlink" title="获取Class对象的四种方式："></a>获取Class对象的四种方式：</h2><p>如果我们动态获取到这些信息，我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。Java 提供了四种方式获取 Class 对象:</p>
<p><strong>1.知道具体类的情况下可以使用：</strong></p>
<pre><code class="java">Class alunbarClass = TargetObject.class;
</code></pre>
<p>但是我们一般是不知道具体类的，基本都是通过遍历包下面的类来获取 Class 对象，通过此方式获取Class对象不会进行初始化</p>
<p><strong>2.通过 <code>Class.forName()</code>传入类的路径获取：</strong></p>
<pre><code class="java">Class alunbarClass1 = Class.forName(&quot;cn.javaguide.TargetObject&quot;);
</code></pre>
<p>Class.forName(className)方法，内部实际调用的是一个native方法 forName0(className, true, ClassLoader.getClassLoader(caller), caller);</p>
<p>第2个boolean参数表示类是否需要初始化，Class.forName(className)默认是需要初始化。</p>
<p>一旦初始化，就会触发目标对象的 static块代码执行，static参数也会被再次初始化。</p>
<p><strong>3.通过对象实例<code>instance.getClass()</code>获取：</strong></p>
<pre><code class="java">Employee e = new Employee();
Class alunbarClass2 = e.getClass();
</code></pre>
<p><strong>4.通过类加载器<code>xxxClassLoader.loadClass()</code>传入类路径获取：</strong></p>
<pre><code class="java">class clazz = ClassLoader.LoadClass(&quot;cn.javaguide.TargetObject&quot;);
</code></pre>
<p>通过类加载器获取Class对象不会进行初始化，意味着不进行包括初始化等一些列步骤，静态块和静态对象不会得到执行</p>
<h2 id="代码："><a href="#代码：" class="headerlink" title="代码："></a>代码：</h2><p>1.创建一个我们要使用反射操作的类 <code>TargetObject</code>：</p>
<pre><code class="java">package cn.javaguide;

public class TargetObject &#123;
    private String value;

    public TargetObject() &#123;
        value = &quot;JavaGuide&quot;;
    &#125;

    public void publicMethod(String s) &#123;
        System.out.println(&quot;I love &quot; + s);
    &#125;

    private void privateMethod() &#123;
        System.out.println(&quot;value is &quot; + value);
    &#125;
&#125;
</code></pre>
<p>2.使用反射操作这个类的方法以及参数</p>
<pre><code class="java">package cn.javaguide;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main &#123;
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException &#123;
        /**
         * 获取TargetObject类的Class对象并且创建TargetObject类实例
         */
        Class&lt;?&gt; tagetClass = Class.forName(&quot;cn.javaguide.TargetObject&quot;);
        TargetObject targetObject = (TargetObject) tagetClass.newInstance();
        /**
         * 获取所有类中所有定义的方法
         */
        Method[] methods = tagetClass.getDeclaredMethods();
        for (Method method : methods) &#123;
            System.out.println(method.getName());
        &#125;
        /**
         * 获取指定方法并调用
         */
        Method publicMethod = tagetClass.getDeclaredMethod(&quot;publicMethod&quot;,
                String.class);

        publicMethod.invoke(targetObject, &quot;JavaGuide&quot;);
        /**
         * 获取指定参数并对参数进行修改
         */
        Field field = tagetClass.getDeclaredField(&quot;value&quot;);
        //为了对类中的参数进行修改我们取消安全检查，这就是反射机制的安全隐患？
        field.setAccessible(true);
        field.set(targetObject, &quot;JavaGuide&quot;);
        /**
         * 调用 private 方法
         */
        Method privateMethod = tagetClass.getDeclaredMethod(&quot;privateMethod&quot;);
        //为了调用private方法我们取消安全检查
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);
    &#125;
&#125;
</code></pre>
<p>输出内容：</p>
<pre><code>publicMethod
privateMethod
I love JavaGuide
value is JavaGuide
</code></pre>
<h2 id="静态编译和动态编译："><a href="#静态编译和动态编译：" class="headerlink" title="静态编译和动态编译："></a>静态编译和动态编译：</h2><ul>
<li><strong>静态编译：</strong> 在编译时确定类型，绑定对象</li>
<li><strong>动态编译：</strong> 运行时确定类型，绑定对象</li>
</ul>
<h2 id="反射机制优缺点："><a href="#反射机制优缺点：" class="headerlink" title="反射机制优缺点："></a>反射机制优缺点：</h2><ul>
<li><strong>优点：</strong> 运行期类型的判断，动态加载类，提高代码灵活度。</li>
<li><strong>缺点：</strong> 1,性能瓶颈：反射相当于一系列解释操作，通知 JVM 要做的事情，性能比直接的 java 代码要慢很多。2,安全问题，让我们可以动态操作改变类的属性同时也增加了类的安全隐患。</li>
</ul>
<h2 id="反射的应用场景："><a href="#反射的应用场景：" class="headerlink" title="反射的应用场景："></a>反射的应用场景：</h2><p><strong>反射是框架设计的灵魂。</strong></p>
<p>在我们平时的项目开发过程中，基本上很少会直接使用到反射机制，但这不能说明反射机制没有用，实际上有很多设计、开发都与反射机制有关，例如模块化的开发，通过反射去调用对应的字节码；动态代理设计模式也采用了反射机制，还有我们日常使用的 Spring／Hibernate 等框架也大量使用到了反射机制。</p>
<p>举例：</p>
<ol>
<li>我们在使用 JDBC 连接数据库时使用 <code>Class.forName()</code>通过反射加载数据库的驱动程序；</li>
<li>Spring 框架的 IOC（动态加载管理 Bean）创建对象以及 AOP（动态代理）功能都和反射有联系；</li>
<li>动态配置实例的属性；</li>
<li>……</li>
</ol>

      
    </div>
    
    
    <div class="article-category">
      
        <b>Categories:</b>
        <a class="article-category-link" href="/categories/java%E7%90%86%E8%AE%BA/">java理论</a>
      
      
        <br/>
      
      
        <b>Tags:</b>
        <a class="article-tag-none-link" href="/tags/java/" rel="tag">java</a>
      
    </div>
    
    
  </div>
</article>

  
<nav id="article-nav" class="article-nav">
  
    <a href="/2021/05/05/%E3%80%8A%E4%B8%80%E4%B8%80%E3%80%8B/" id="article-nav-newer" class="article-nav-link-wrap newer">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          《一一》
        
      </div>
    </a>
  
  
    <a href="/2021/01/11/java%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F/" id="article-nav-older" class="article-nav-link-wrap older">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">
        
          java代理模式
        
      </div>
    </a>
  
</nav>






    </div>
  </div>
  




<div id="settings-container">
  <div id="dark-mode">dark</div>
  <div id="sans-font">sans</div>
</div>
<script type="text/javascript">
let d=document,r=d.documentElement.style,f=r.setProperty.bind(r),l=localStorage,s=l.getItem('s')||(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches),n=l.getItem('n'),m=d.getElementById("dark-mode"),b=()=>{f('--bg-color','#fafafa');f('--code-bg-color','#f4f4f4');f('--text-color','#212121');f('--secondary-color','#808080');f('--tertiary-color','#b0b0b0');f('--link-color','#b5c8cf');f('--link-hover-color','#618794');f('--link-bg-color','#dae4e7');f('--selection-color','#dae4e7');m.innerHTML="dark"},c=()=>{f('--bg-color','#212121');f('--code-bg-color','#292929');f('--text-color','#fff');f('--secondary-color','#c0c0c0');f('--tertiary-color','#6e6e6e');f('--link-color','#4d6b75');f('--link-hover-color','#96b1bb');f('--link-bg-color','#5d828e');f('--selection-color','#acc1c9');m.innerHTML="light"},o=d.getElementById("sans-font"),e=()=>{f('--body-stack','"Lora", "Georgia", "Times New Roman", serif');o.innerHTML="sans"},g=()=>{f('--body-stack','"Lato", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", "Verdana", sans-serif');o.innerHTML="serif"};m.onclick=()=>{if(s==2){s=1;l.setItem('s',s);c()}else{s=2;l.setItem('s',s);b()}};o.onclick=()=>{if(n==2){n=1;l.setItem('n',n);g()}else{n=2;l.setItem('n',n);e()}};if(!s){s=2;l.setItem('s',2)};if(s==1){c()};if(!n){n=2;l.setItem('n',2)};if(n==1){g()};
</script>




</body>
</html>
